import random, math
from PIL import Image, ImageDraw, ImageFont, ImageFilter


class vieCode:
	__fontSize = 20  # 字体大小
	__width = 120  # 画布宽度
	__heigth = 45  # 画布高度
	__length = 4  # 验证码长度
	__draw = None  # 画布
	__img = None  # 图片资源
	__code = None  # 验证码字符
	__str = None  # 自定义验证码字符集
	__inCurve = True  # 是否画干扰线
	__inNoise = True  # 是否画干扰点
	__type = 2  # 验证码类型 1、纯字母  2、数字字母混合
	__fontPatn = 'applications/common/utils/fonts/1.ttf'  # 字体

	def GetCodeImage(self, size=80, length=4):
		'''获取验证码图片
		   @param int size 验证码大小
		   @param int length 验证码长度
		'''
		# 准备基础数据
		self.__length = length
		self.__fontSize = size
		self.__width = self.__fontSize * self.__length
		self.__heigth = int(self.__fontSize * 1.5)

		# 生成验证码图片
		self.__createCode()
		self.__createImage()
		# self.__createNoise()
		self.__printString()
		self.__cerateFilter()

		return self.__img, self.__code

	def __cerateFilter(self):
		'''模糊处理'''
		self.__img = self.__img.filter(ImageFilter.BLUR)
		filter = ImageFilter.ModeFilter(8)
		self.__img = self.__img.filter(filter)

	def __createCode(self):
		'''创建验证码字符'''
		# 是否自定义字符集合
		if not self.__str:
			# 源文本
			number = "3456789"
			srcLetter = "qwertyuipasdfghjkzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"
			srcUpper = srcLetter.upper()
			if self.__type == 1:
				self.__str = number
			else:
				self.__str = srcLetter + srcUpper + number

		# 构造验证码
		self.__code = random.sample(self.__str, self.__length)

	def __createImage(self):
		'''创建画布'''
		bgColor = (random.randint(200, 255), random.randint(200, 255), random.randint(200, 255))
		self.__img = Image.new('RGB', (self.__width, self.__heigth), bgColor)
		self.__draw = ImageDraw.Draw(self.__img)

	def __createNoise(self):
		'''画干扰点'''
		if not self.__inNoise:
			return
		font = ImageFont.truetype(self.__fontPatn, int(self.__fontSize / 1.5))
		for i in range(5):
			# 杂点颜色
			noiseColor = (random.randint(150, 200), random.randint(150, 200), random.randint(150, 200))
			putStr = random.sample(self.__str, 2)
			for j in range(2):
				# 绘杂点
				size = (random.randint(-10, self.__width), random.randint(-10, self.__heigth))
				self.__draw.text(size, putStr[j], font=font, fill=noiseColor)
		pass

	def __createCurve(self):
		'''画干扰线'''
		if not self.__inCurve:
			return
		x = y = 0

		# 计算曲线系数
		a = random.uniform(1, self.__heigth / 2)
		b = random.uniform(-self.__width / 4, self.__heigth / 4)
		f = random.uniform(-self.__heigth / 4, self.__heigth / 4)
		t = random.uniform(self.__heigth, self.__width * 2)
		xend = random.randint(self.__width / 2, self.__width * 2)
		w = (2 * math.pi) / t

		# 画曲线
		color = (random.randint(30, 150), random.randint(30, 150), random.randint(30, 150))
		for x in range(xend):
			if w != 0:
				for k in range(int(self.__heigth / 10)):
					y = a * math.sin(w * x + f) + b + self.__heigth / 2
					i = int(self.__fontSize / 5)
					while i > 0:
						px = x + i
						py = y + i + k
						self.__draw.point((px, py), color)
						i -= i

	def __printString(self):
		'''打印验证码字符串'''
		# font = ImageFont.truetype(self.__fontPatn, self.__fontSize)
		font = ImageFont.truetype(r'C:\Windows\Fonts\arial.ttf', self.__fontSize)
		x = 0
		# 打印字符到画板
		for i in range(self.__length):
			# 设置字体随机颜色
			color = (random.randint(30, 150), random.randint(30, 150), random.randint(30, 150))
			# 计算座标
			x = random.uniform(self.__fontSize * i * 0.95, self.__fontSize * i * 1.1)
			y = self.__fontSize * random.uniform(0.3, 0.5)
			# 打印字符
			self.__draw.text((x, y), self.__code[i], font=font, fill=color)
			# print(self.__code[i])
if __name__ == '__main__':
	img,code=vieCode().GetCodeImage(size=80, length=4)
	print(code)
	print(img)
	img.show()